import { Effect, ImmerReducer, Reducer, Subscription } from 'umi';
import { getRemoteList, editRecord, deleteRecord, addRecord } from './service';
import { message } from 'antd';
import { UserState } from './data';

// todo ts类型定义
interface UserModelType {
  namespace: 'users';
  state: UserState;
  reducers: {
    getList: Reducer<UserState>;
  };
  effects: {
    getRemote: Effect;
    edit: Effect;
    delete: Effect;
    add: Effect;
  };
  subscriptions: {
    setup: Subscription;
  };
}

const UserModel: UserModelType = {
  namespace: 'users',
  // 规定好类型之后就不能为空
  state: {
    data: [],
    meta: {},
  },
  // todo 同步
  reducers: {
    // 它里面的参数格式都是 state, action
    // 说明：action = {type, payload}
    getList(state, action) {
      return action.payload;
    },
  },
  // todo 异步
  effects: {
    // 说明：action = {type, payload}
    // 说明：effects = { put, call, select}  // *select可以取到state的数据

    // todo 获取初始数据
    *getRemote({ payload: { per_page, page } }, effects) {
      // 使用 call 来触发异步的接口函数（后面是参数）
      const data = yield effects.call(getRemoteList, per_page, page);
      // 使用 put 触发 reducers
      if (data) {
        yield effects.put({
          type: 'getList',
          payload: data,
        });
        message.success('获取数据成功');
      }
    },

    // todo 编辑数据，第一个只能是参数名称，后面才能传数据
    *edit(action, effects) {
      const data = yield effects.call(
        editRecord,
        action.payload.id,
        action.payload
      );
      //  state为0，就是成功
      if (data.state === 0) {
        message.success('修改成功');
        // todo 重新调用 getRemote 来获取数据
        const { page, per_page } = yield effects.select((state: any) => {
          return state.users.meta;
        });

        yield effects.put({
          type: 'getRemote',
          payload: {
            page,
            per_page,
          },
        });
      }
    },

    // todo 新增数据，第一个只能是参数名称，后面才能传数据
    *add(action, effects) {
      const data = yield effects.call(addRecord, action.payload);
      //  state为0，就是成功
      if (data.state === 0) {
        message.success('添加成功，重新获取数据');
        // todo 重新调用 getRemote 来获取数据
        const { page, per_page } = yield effects.select((state: any) => {
          return state.users.meta;
        });

        yield effects.put({
          type: 'getRemote',
          payload: {
            page,
            per_page,
          },
        });
      }
    },

    // todo 删除字段，参数是id（后端这个接口貌似有点问题）
    *delete(action, effects) {
      const data = yield effects.call(deleteRecord, action.payload.id);

      //  state 为0，就是成功
      if (data.state === 0) {
        message.success('删除成功');
        // todo 重新调用 getRemote 来获取数据

        const { page, per_page } = yield effects.select((state: any) => {
          return state.users.meta;
        });

        yield effects.put({
          type: 'getRemote',
          payload: {
            page,
            per_page,
          },
        });
      }
    },
  },
  // todo 路由监听
  subscriptions: {
    setup({ dispatch, history }) {
      return history.listen((location, action) => {
        // 参数可以直接简写成{pathname}
        if (location.pathname === '/users') {
          // todo 触发 effects 下的对应函数

          // ! 如果使用了 antdPro 的 request，就不需要这个进行触发
          dispatch({
            // 会对接到effects 和 reducers
            type: 'getRemote',
            // 习惯是把所有的参数都放到下面的对象里(除了type)
            payload: {
              per_page: 5,
              page: 1,
            },
          });
        }
      });
    },
  },
};
export default UserModel;
